package org.fly.service.impl;

import org.apache.commons.lang.StringUtils;
import org.fly.bean.Classification;
import org.fly.bean.Page;
import org.fly.bean.query.ClassificationQuery;
import org.fly.bean.warpper.ClassificationTreeWarpper;
import org.fly.bean.warpper.ClassificationWarpper;
import org.fly.contants.WebConstant;
import org.fly.dao.ClassificationDao;
import org.fly.enums.Status;
import org.fly.service.ClassificationService;
import org.fly.utils.UUIDFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author  fly
 */
@Service
public class ClassificationServiceImpl implements ClassificationService {

    @Autowired
    ClassificationDao classificationDao;


    @Override
    public List<ClassificationWarpper> listWarpper(ClassificationQuery query) {
        List<Classification>  list =  classificationDao.list(query);
        List<String> parentIdList = list.stream().filter(e->StringUtils.isNotBlank(e.getParentId())).
                map(e->e.getParentId()).collect(Collectors.toList());
        Map<String,Classification>  pmap = new HashMap<>();
        if(!parentIdList.isEmpty()){
            List<Classification>  pList =  classificationDao.listByIdList(parentIdList);
            pList.forEach(e->{
                pmap.put(e.getId(),e);
            });
        }
        List<ClassificationWarpper> warpperList = list.stream().map(e->{
            ClassificationWarpper warpper = new ClassificationWarpper();
            BeanUtils.copyProperties(e,warpper);
            if(StringUtils.isNotBlank(e.getParentId()) ){
                warpper.setParent(pmap.get(e.getParentId()));
            }
            return warpper;
        }).collect(Collectors.toList());
        return warpperList;
    }

    @Override
    public List<Classification> list(ClassificationQuery query) {
        return classificationDao.list(query);
    }

    @Override
    public long count(ClassificationQuery query) {
        return classificationDao.count(query);
    }

    @Transactional
    @Override
    public void save(Classification classification) {
        long sort = 0;
        String pSortStr ="";
        if(StringUtils.isNotBlank(classification.getParentId())){
            Classification p = classificationDao.findById(classification.getParentId());
            pSortStr = p.getSortStr();
            sort = p.getIndex()*WebConstant.pLevel+classification.getIndex();
        }else{
            sort = classification.getIndex()*WebConstant.pLevel;
            if(StringUtils.isNotBlank(classification.getId())){
                classificationDao.updateChildSort(classification.getId(),sort);
            }

        }
        classification.setSort(sort);
        if(StringUtils.isNotBlank(classification.getId())){
            Classification db =  classificationDao.findById(classification.getId());
            classification.setSortStr(pSortStr+ WebConstant.splitStr+classification.getIndex()+WebConstant.splitStr+
                    db.getCreateTime());
            classificationDao.update(classification);

        }else {
            long createTime =  System.currentTimeMillis();
            classification.setId(UUIDFactory.random());
            classification.setCreateTime(createTime);
            classification.setSortStr(pSortStr+WebConstant.splitStr+classification.getIndex()+WebConstant.splitStr+
                    classification.getCreateTime());
            classificationDao.insert(classification);

        }
    }

    @Override
    public List<Classification> listByParentId(String parentId) {
        return null;
    }

    @Override
    public Classification findById(String id) {
        return classificationDao.findById(id);
    }

    @Override
    public void delete(String id) {
        classificationDao.delete(id);
    }

    @Override
    public List<ClassificationTreeWarpper> treeMapAll() {
        ClassificationQuery query =  new ClassificationQuery();
        query.setStatus(Status.valid.name());
        List<Classification> clazzList = classificationDao.list(query);
        Map<String,ClassificationTreeWarpper> map  = new HashMap<>();
        clazzList.stream().map(e->{
            ClassificationTreeWarpper warpper = new ClassificationTreeWarpper();
            BeanUtils.copyProperties(e,warpper);
            return warpper;
        }).forEach(node->{
            String id = node.getId();
            String pId = node.getParentId();
            //如果map中已经存在对应备案,则说明之前遍历到过它的子节点，用该节点替换掉伪造的节点
            if(map.get(id) != null){
                ClassificationTreeWarpper _node =  map.get(id);
                List<ClassificationTreeWarpper> _nodeChildren = _node.getSubList();
                node.setSubList(_nodeChildren);
            }
            map.put(node.getId(),node);
            if(!StringUtils.isBlank(pId)){
                ClassificationTreeWarpper  _p =  map.get(pId);
                // 说明 父节点已经便利过了,或者他的兄弟已经遍历过了
                if(_p != null ){
                    List<ClassificationTreeWarpper> _treeNodes =  _p.getSubList();
                    if(_treeNodes == null ){
                        _treeNodes = new ArrayList<>();
                        _p.setSubList(_treeNodes);
                    }
                    _treeNodes.add(node);
                }else {
                    //如果父节点还没有遍历到，先伪造一个父节点存储子节点数据
                    _p =  new ClassificationTreeWarpper();
                    map.put(pId,_p);
                    List<ClassificationTreeWarpper> _treeNodes = new ArrayList<>();
                    _p.setSubList(_treeNodes);
                    _treeNodes.add(node);
                }
            }
        });
        List<ClassificationTreeWarpper> warpperList= map.entrySet().stream().filter(
                e->StringUtils.isBlank( e.getValue().getParentId())&& StringUtils.isNotBlank(e.getValue().getId())).map(e->e.getValue()).
                sorted(Comparator.comparing(Classification::getIndex)).collect(Collectors.toList());
        return warpperList;
    }
}
